#include "Logger.h"
#include "TcpServer.h"
#include "TcpClient.h"
#include <algorithm>
#include <memory>
#include <sstream>
#include <string>
#include <vector>

class EchoSession {
public:
    using Ptr = std::shared_ptr<EchoSession>;
    EchoSession() = default;
    ~EchoSession() = default;

    std::string m_Data;
    int m_SendStart = 0;

    void HandleRead(std::shared_ptr<GiSo::TcpConnection> conn, GiSo::Buffer& buffer) {
        buffer.AssignToString(m_Data);
        if(m_Data.back() != '\n') {
            return;
        }
        std::stringstream ss(m_Data);
        std::vector<int> numbers;
        int num;
        while(ss >> num) {
            numbers.push_back(num);
        }
        std::sort(numbers.begin(), numbers.end());
        std::stringstream response_ss;
        for(int i = 0; i < numbers.size(); ++i) {
            response_ss << numbers[i] << (i == numbers.size() - 1 ? "" : " ");
        }
        m_Data = response_ss.str();
        m_Data += "\n";
        if(!conn->Send(m_Data)){
            GS_ERROR("fuck............");
        }
    }

    void HandleWriteComplete(std::shared_ptr<GiSo::TcpConnection> conn) {
        GS_INFO("Server {0} TcpConnection::HandleWriteComplete", conn->GetFd());
    }

    void HandleClose(std::shared_ptr<GiSo::TcpConnection> conn) {
        GS_INFO("Server {0} TcpConnection::HandleClose", conn->GetFd());
    }

    static bool AddSession(GiSo::TcpConnection::Ptr conn, const GiSo::InetAddress& clientAddr) {
        GS_INFO("Server New connection from {0}:{1}", clientAddr.GetIp(), clientAddr.GetPort());
        EchoSession::Ptr session = std::make_shared<EchoSession>();
        conn->SetReadCallback(std::bind(&EchoSession::HandleRead, session, std::placeholders::_1, std::placeholders::_2));
        conn->SetWriteCompleteCallback(std::bind(&EchoSession::HandleWriteComplete, session, std::placeholders::_1));
        conn->SetCloseCallback(std::bind(&EchoSession::HandleClose, session, std::placeholders::_1));
        return true;
    }
};

void RunClient(){
    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    GiSo::TcpClient client;
    std::vector<int> dataToSend(3000);
    for(int i=0;i<3000;i++){
        dataToSend[i] = 3000-i;
    }
    if(client.ConnectToServer("127.0.0.1", 1126)){
        std::stringstream ss;
        for (int i = 0; i < dataToSend.size(); ++i) {
            ss << dataToSend[i] << (i == dataToSend.size() - 1 ? "" : " ");
        }
        ss<<"\n";
        client.SendData(ss.str());
        GS_INFO("Client sent data");
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        std::string receiveData = " ";
        while(client.Wait(2000)){
            std::string&& data = client.ReceiveData();
            receiveData += data;
            if(data.back() == '\n'){
                GS_INFO(receiveData);
                client.Disconnect();
                break;
            }
        }
    }
    else{
        GS_INFO("Client connect failed");
    }
    
}

int main() {
    GiSo::InetAddress addr(1126); // Different port for echo server
    GiSo::TcpServer server(addr, 3);
    server.SetNewConnectionCallback(EchoSession::AddSession);

    GS_INFO("Echo server listening on port 1126");

    std::thread clientThread(RunClient);

    server.Start();
    clientThread.join();

    return 0;
}